package aishua.com.mytestapplist.apdu;

/**
 * Created by aishua on 2017/7/12.
 */

import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;

import org.simalliance.openmobileapi.Channel;
import org.simalliance.openmobileapi.Reader;
import org.simalliance.openmobileapi.SEService;
import org.simalliance.openmobileapi.Session;

import java.io.IOException;

import aishua.com.mytestapplist.MyApplication;
import aishua.com.mytestapplist.utils.CommonMethods;
import aishua.com.mytestapplist.utils.LogUtils;


/**
 * 做必要的初始化，context channel等相关的初始化工作
 *
 * @author Jack
 *
 */
public class SeServiceHandler  {
    
    private final static String TAG = "SeServiceHandler";
    private Object waitSEServiceConnected;
    private Reader mReader;
    private Channel mChannel;
    private SEService mSeService;
    private Session mSession;
    private static SeServiceHandler mSeHandler = new SeServiceHandler();
    private String text = "cecececececece";
    private SeServiceHandler() {
    };

    /**
     * 得到为null channel打不开
     * @return
     */
    public static SeServiceHandler getSeHandler() {
//		closeChannel();
//		mCtx = context;
        return mSeHandler;
    }

    public String getText(){
        return text;
    }
    public void setText(String text){
        this.text = text;
    }
    boolean wait = false;
    long waitTime = 2000;//milliseconds
    public void initService(Context ctx){
//		//@may problem
//		LogUtils.v(" initService()---> mChannel= "+mChannel);
//		if(mChannel!=null){
//			closeChannel();
//			return;
//		}
        //@may problem  这个地方有问题，最好每次都用新的服务，先屏蔽掉试下
//		if(mSeService!=null&&mSession!=null){
//
//			if(mSeService.isConnected()&&!mSession.isClosed()){
//				System.out.println("use old service & session");
//				LogUtils.v("use old service & session");
//				return;
//			}
//			LogUtils.v(" old service & session  disabled ");
//		}
        close();
//		if(mSeService!=null){
//			if (mSeService.isConnected()) {
//				mSeService.shutdown();
//			}
//			mSeService = null;
//		}
        if(getConnectedSEService(ctx)){
            boolean openSIMChannelOk = openSIMChannel(mSeService);
            LogUtils.v("openSIMChannelOk= "+openSIMChannelOk);
            //wallet src
//			openSIMChannel_wallet();
        }
        LogUtils.v("get seservice success");
//		text = ;
    }

    private void closeChannel() {
        if (mChannel != null) {
            if (!mChannel.isClosed()) {
                mChannel.close();
            }
            mChannel = null;
        }
    }

    public boolean getConnectedSEService(Context context) {
        try {

            if (waitSEServiceConnected == null) {
                waitSEServiceConnected = new Object();
            }
            if (mSeService != null) {
                if (mSeService.isConnected()) {
                    mSeService.shutdown();
                }
                mSeService = null;
            }
            mSeService = new SEService(context, new SEInfoServieCB());
            for (int i = 0; i < 3; i++) {
                synchronized (waitSEServiceConnected) {
                    try {
                        waitSEServiceConnected.wait(4000);
                        if (!mSeService.isConnected()) {
                            continue;
                        } else {
                            break;
                        }
                    } catch (InterruptedException e) {

                        // CTWalletLog.print("Se_OPR_SERVICE",
                        // "waitSEServiceConnected interruptted! But relax, it's Ok.");
                        MyApplication.mIsNotNFCDevices = true;
//						CTWalletLog.print(TAG+ "getConnectedSEService()-waitSEServiceConnected interruptted! But relax, it's Ok.");
                    }
                }
            }

            // throw new NoClassDefFoundError("text");
            if (mSeService.isConnected()) {
                return true;
            }
        } catch (NoClassDefFoundError e) {
            MyApplication.mIsNotNFCDevices = true;
        }
        return false;
    }

    public boolean checkDevices() {

        return MyApplication.mIsNotNFCDevices;
    }

    public void close(){

        LogUtils.v("close all : channle  mSession  mReader  mSeService");
        closeChannel();
        if (mSession != null) {
            if (!mSession.isClosed()) {
                mSession.close();
            }
            mSession = null;
        }
        if (mReader != null) {
            mReader.closeSessions();
            mReader = null;
        }
        if (mSeService != null) {
            if (mSeService.isConnected()) {
                mSeService.shutdown();
            }
            mSeService = null;
        }
    }

    private class SEInfoServieCB implements SEService.CallBack {

        public SEInfoServieCB() {

        }

        public void serviceConnected(SEService arg0) {
            synchronized (waitSEServiceConnected) {
                waitSEServiceConnected.notifyAll();
            }
        }
    }

    private boolean openSIMChannel(SEService seService) {

        getSimReader(seService);
        if (mReader == null) {
            return false;
        }
        try {
            mSession = mReader.openSession();
            if (mSession == null) {
                MyApplication.mIsNotNFCDevices = true;
                return false;
            }
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            MyApplication.mIsNotNFCDevices = true;
            LogUtils.v(e.getMessage());
        }
        return false;
    }

    private void getSimReader(SEService seService) {
//		if (mReader != null) {
//			 mReader.closeSessions();
//			mReader = null;
//		}
        Reader[] readers = seService.getReaders();
        for (Reader reader : readers) {
            if (reader.getName().startsWith("SIM")) {
                LogUtils.v("reader= "+reader);
                LogUtils.v("reader name= "+reader.getName());
                mReader = reader;
                break;
            }
        }
//		return mReader;
    }

    public String getSeid() {
//			byte[] buff = CommonMethods.str2bytes("A0000001510000");
        mChannel = openLogicalChannel("A0000001510000");
        if(mChannel==null){
            return "";
        }
       LogUtils.v("主安全域返回 = "+ CommonMethods.bytesToHexString(mChannel.getSelectResponse()));
        String res = transmitApdu("80CA00110C");
        LogUtils.v("res--->"+res);
        String seid = "";
        if (res.endsWith("9000") && res.length() >= 24) {
            seid = res.substring(res.length() - 24, res.length() - 4);
            seid = CommonMethods.exchangeHighAndLow(seid);
        }

        return seid;

    }
    public Channel openLogicalChannel(String aid) {
        try {
            if(mSession==null){
                return null;
            }
            //@test  每次打开前关闭通道。
            if (mChannel != null) {
                mChannel.close();
                mChannel = null;
            }
            mChannel = mSession.openLogicalChannel(CommonMethods.str2bytes(aid));
            if (mChannel == null) {
//				return mChannel;
            }
            return mChannel;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    public String transmitApdu(String commString) {
        try {
            if(mChannel==null){
                close();
                throw new RuntimeException("the channel is null service close");
            }
            byte[] res = mChannel.transmit(CommonMethods.str2bytes(commString));
            return CommonMethods.bytesToHexString(res);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
}
